﻿// Author: Jithu Jose, Email: jithu89@hotmail.it
// 
// This file is part of Schedule.
//
// Schedule is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Schedule is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Lesser General Public License for more details.
// 
// You should have received a copy of the GNU Lesser General Public License
// along with Schedule.  If not, see <http://www.gnu.org/licenses/>.

namespace JJware.Schedule
{
    using System;
    using System.Collections.Generic;
    using System.Diagnostics;
    using System.Drawing;
    using System.IO;
    using System.Windows.Forms;

    public partial class FrmMain : Form
    {
        #region Fields

        private Point _endLocation = new Point();
        private Point _startLocation = new Point();
        // internal items list
        private List<ItemInfo> _items;
        private bool _mouseClicked/* = false*/;
        private bool _startMonitoring/* = false*/;
        private string _timerText = "";
        private const string _aboutBoxMessage = "Title: Schedule\n" +
                        "Author: Jithu Jose\n" +
                        "Description: This utility program can help you schedule files,programs startup.";

        #endregion Fields

        #region Constructors

        /// <summary>
        /// Default constructor of the main form class
        /// </summary>
        public FrmMain()
        {
            InitializeComponent();
            UpdateTimer();
            _items = new List<ItemInfo>();
        }

        #endregion Constructors

        #region Methods

        /// <summary>
        /// Update Items
        /// </summary>
        /// <param name="newItem">If not null, it is added to the items list</param>
        public void UpdateItems(ItemInfo newItem)
        {
            _startMonitoring = true;
            if (newItem != null) _items.Add(newItem);

            UpdateItems(false);
        }

        /// <summary>
        /// Loads items from a text file to the list view.
        /// </summary>
        private void LoadFromFile()
        {
            OpenFileDialog ofd = new OpenFileDialog();
            if (ofd.ShowDialog() == DialogResult.OK)
            {
                if (File.Exists(ofd.FileName))
                {
                    try
                    {
                        using (StreamReader reader = new StreamReader(ofd.FileName))
                        {
                            while (!reader.EndOfStream)
                            {
                                string currentLine = reader.ReadLine();
                                string path = currentLine.Substring(0, currentLine.IndexOf('@'));
                                string time = currentLine.Substring(path.Length + 1);
                                string[] splitted_time = time.Split(':');

                                ItemInfo item = new ItemInfo(path,
                                    new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day,
                                        int.Parse(splitted_time[0]), int.Parse(splitted_time[1]),
                                        int.Parse(splitted_time[2])));
                                UpdateItems(item);
                            }
                        }
                    }
                    catch (ObjectDisposedException ex)
                    {
                        MessageBox.Show(ex.Message, "Error while parsing the input file",
                            MessageBoxButtons.OK, MessageBoxIcon.Error);
                    }
                    UpdateUI();
                }
            }
        }

        /// <summary>
        /// Removes selected items.
        /// </summary>
        /// <param name="selectedIndices">Selected indices</param>
        private void RemoveItems(ListView.SelectedIndexCollection selectedIndices)
        {
            if (selectedIndices.Count > 0)
            {
                int count = selectedIndices.Count;
                int[] indices = new int[count];
                for (int i = 0; i < count; i++)
                    indices[i] = selectedIndices[i];
                Array.Sort(indices);

                for (int i = 0; i < count; i++)
                {
                    _items.RemoveAt(indices[i]);
                    for (int j = i + 1; j < count; j++)
                        indices[j]--;
                }
            }

            UpdateItems(false);
        }

        /// <summary>
        /// Save the contents of the _items list to a file.
        /// </summary>
        private void SaveToFile()
        {
            SaveFileDialog sfd = new SaveFileDialog();
            if (sfd.ShowDialog() == DialogResult.OK)
            {
                StreamWriter writer = new StreamWriter(File.Create(sfd.FileName));

                for (int i = 0; i < _items.Count; i++)
                {
                    writer.WriteLine(_items[i].Path + "@" +
                        _items[i].Time.Hour + ":" + _items[i].Time.Minute +
                        ":" + _items[i].Time.Second);
                }
                writer.Close();
                Program.ShowMessage("Save successful!");
            }
        }

        /// <summary>
        /// Update the form location.
        /// </summary>
        private void UpdateFormLocation()
        {
            int dx = _startLocation.X - _endLocation.X;
            int dy = _startLocation.Y - _endLocation.Y;

            Location = new Point(Location.X - dx, Location.Y - dy);
            _startLocation = _endLocation;
        }

        /// <summary>
        /// Update items with the internal _items list.
        /// </summary>
        /// <param name="clearItems">true: clears the internal items list.
        /// false: doesn't clear the internal items list.</param>
        private void UpdateItems(bool clearItems)
        {
            lvItems.Items.Clear();
            if (clearItems)
            {
                _items.Clear();
                return;
            }

            UpdateListView();
        }

        /// <summary>
        /// Load items from _items list to list view.
        /// </summary>
        private void UpdateListView()
        {
            for (int i = 0; i < _items.Count; ++i)
            {
                ListViewItem item = new ListViewItem();
                item = new ListViewItem(_items[i].Path);
                item.SubItems.Add(_items[i].Time.Hour.ToString() + " : " +
                                  _items[i].Time.Minute.ToString() + " : " +
                                  _items[i].Time.Second.ToString());
                lvItems.Items.Add(item);
            }
        }

        /// <summary>
        /// Update internal timer.
        /// </summary>
        private void UpdateTimer()
        {
            _timerText = DateTime.Now.Hour.ToString() + ":" + DateTime.Now.Minute.ToString() +
                ":" + DateTime.Now.Second.ToString();
            lblTimerOutput.Text = _timerText;

            if (_startMonitoring)
            {
                for (int i = 0; i < _items.Count; ++i)
                {
                    if (_items[i].Time.Hour == DateTime.Now.Hour &&
                        _items[i].Time.Minute == DateTime.Now.Minute &&
                        _items[i].Time.Second == DateTime.Now.Second)
                    {
                        Process.Start(_items[i].Path);
                        _items.RemoveAt(i);
                        UpdateItems(false);
                    }
                }
            }
        }

        /// <summary>
        /// Update UI accessibility.
        /// </summary>
        private void UpdateUI()
        {
            btnRemove.Enabled = btnSave.Enabled = _startMonitoring;
        }

        /// <summary>
        /// Event Handler: Show about form.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnAbout_Click(object sender, EventArgs e)
        {
            MessageBox.Show(this, _aboutBoxMessage, "About Schedule");
        }

        /// <summary>
        /// Event Handler: Show the frmAddNewItem form inorder to add a new item to the list view.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnAdd_Click(object sender, EventArgs e)
        {
            FrmAddNewItem _frmAddNewItem = new FrmAddNewItem(DateTime.Now, this);
            _frmAddNewItem.ShowDialog();
            UpdateUI();
        }

        /// <summary>
        /// Event Handler: Close the main application.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnClose_Click(object sender, EventArgs e)
        {
            Close();
        }

        /// <summary>
        /// Event Handler: Load items from a file.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnLoad_Click(object sender, EventArgs e)
        {
            LoadFromFile();
        }

        /// <summary>
        /// Event Handler: Remove all selected items from the list view.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnRemove_Click(object sender, EventArgs e)
        {
            if (lvItems.SelectedIndices.Count > 0)
            {
                RemoveItems(lvItems.SelectedIndices);
            }
        }

        /// <summary>
        ///  Event Handler: Save all items in the listview to a text file.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnSave_Click(object sender, EventArgs e)
        {
            if (_items.Count > 0)
            {
                SaveToFile();
            }
        }

        /// <summary>
        /// Event Handler: Invoked when the user keeps the mouse button clicked.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void frmMain_MouseDown(object sender, MouseEventArgs e)
        {
            _startLocation.X = Cursor.Position.X;
            _startLocation.Y = Cursor.Position.Y;
            _mouseClicked = true;
        }

        /// <summary>
        ///  Event Handler: Invoked when the user starts to move the form with mouse.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void frmMain_MouseMove(object sender, MouseEventArgs e)
        {
            if (_mouseClicked)
            {
                _endLocation.X = Cursor.Position.X;
                _endLocation.Y = Cursor.Position.Y;
                UpdateFormLocation();
            }
        }

        /// <summary>
        /// Event Handler: Invoked when the user releases the mouse button.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void frmMain_MouseUp(object sender, MouseEventArgs e)
        {
            _mouseClicked = false;
        }

        /// <summary>
        /// Event Handler: Timer Tick
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void timer_Tick(object sender, EventArgs e)
        {
            UpdateTimer();
        }

        /// <summary>
        /// Event Handler: Invoked when the user clicks the reset button.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnReset_Click(object sender, EventArgs e)
        {
            UpdateItems(true);
        }

        #endregion Methods
    }
}